/**
 * Created with JetBrains WebStorm.
 * User: rren
 * Date: 19/08/13
 * Time: 15:14
 * To change this template use File | Settings | File Templates.
 */
var http = require('http');
var path = require('path');

http.createServer(function(request, response) {
    //console.log("request.url="+request.url);
    //console.log(request.headers);
    //console.log("---------------------------------------------------");

    response.setHeader("Server", "Node-static v1.0 @Ryan.Ren 2013");

    var route = require('./route');
    var pathname = route.routeToClient(request.url);

    if(pathname.length > 1){
        //console.log(pathname);

        var file = require('./file');
        file.exists(pathname, function(exists) {
            if(exists){
                //console.log("File(" + pathname + ") is existed, response the file");
                file.status(pathname, function(error, stat){
                    if(error) throw error;

                    var lastModified = stat.mtime.toUTCString();
                    var ifModifiedSince = "If-Modified-Since".toLowerCase();
                    response.setHeader("Last-Modified", lastModified);

                    var config = require('./config');
                    var mime = require('./mime').types;
                    var ext = path.extname(pathname);
                    ext = ext ? ext.slice(1):'unknown';

                    var contentType = mime[ext]||"text/plain";
                    if(ext.match(config.Expires.fileMatch)) {
                        //console.log("File:"+pathname);
                        var expires = new Date();
                        expires.setTime(expires.getTime() + config.Expires.maxAge*1000);
                        response.setHeader("Expires", expires.toUTCString());
                        response.setHeader("Cache-Control", "max-age=" + config.Expires.maxAge);
                    }

                    //To generate the ETag
                    var fmtime = stat.mtime.getTime().toString(16);
                    var fsize = stat.size.toString(16);
                    var fino = stat.ino;
                    response.setHeader("ETag", fino+"-"+fsize+"-"+fmtime);

                    var acceptEncoding = request.headers['accept-encoding'] || "";
                    //console.log("Client accept encoding is:"+acceptEncoding);
                    var matched = ext.match(config.Compress.match);
                    var streamMode;

                    if(matched && acceptEncoding.match(/\bgzip\b/)) {
                        response.setHeader("Content-Encoding", "gzip");
                        streamMode = "gzip"
                    } else if (matched && acceptEncoding.match(/\bdeflate\b/)){
                        streamMode = "deflate";
                        response.setHeader("Content-Encoding", "deflate");
                    }

                    if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]){
                        response.writeHead(304, "Not Modified");
                        response.end();
                    } else{
                        response.setHeader("Accept-Ranges", "bytes");
                        response.setHeader("Content-Type", contentType);

                        if(request.headers['range']) {
                            //console.log("Request Range content");
                            var range = require('./Range');
                            var requestRange = range.parseRange(request.headers['range'], stat.size);

                            if(requestRange) {
                                response.setHeader("Content-Length", requestRange.end - requestRange.start +1);
                                response.setHeader("Keep-Alive", "timeout=5, max=100");
                                response.setHeader("Content-Range","bytes "+requestRange.start+"-"+requestRange.end+"/"+stat.size);
                                response.writeHead(206, "Partial content");
                                file.readFileStream(pathname, requestRange.start, requestRange.end, streamMode, request, response, function() {
                                    response.end();
                                });
                            } else {
                                response.writeHead(400, "Bad Request");
                                response.end();
                            }
                        } else {
                            //response.setHeader("Content-Length", stat.size);
                            response.writeHead(200, "OK");
                            file.readFileStream(pathname, 0, stat.size-1, streamMode, request, response, function() {
                                response.end();
                            });
                        }
                    }
                });
            }else {
                //console.log("File(" + pathname + ") is not existed, response 404 error");
                response.writeHead(404, {'Content-Type':'text/html'});
                response.write("<head><title>404 Not Found</title></head><body bgcolor = 'white'><center><h1>404 Not Found</h1></center><hr><center>Ryan@Node.js</center></body>");
                response.end();
            }
        });
    }else{
        console.log("Not request File, do something else");
    }
}).listen(8080);

console.log("http server is running on port 8080");
